from celery import shared_task
from django.utils import timezone
from datetime import timedelta
from mysqldb.models import *
from mysqldb import redis as REDIS
from mysqldb.tasks import WeAppsUniformSend
from MoniterManager.tasks import doCallmeEvent
from fsygManager.PulsarSDK import SendAsyncMessage

# from iClouds.PulsarSDK import SendAsyncMessageEx as SAME
# from iClouds.PulsarSDK import send_alert_queue
import asyncio
import math
import json
import random
import logging

logger = logging.getLogger(__name__)
from django.conf import settings


@shared_task
def Dispatch_Reqsn(*args, **kwargs):
    """
    呼叫派单
    dispatch派单模式: 0 前台应答,1 随机派单,2 轮流派单,3 抢单模式,4 固定指派
    status状态: (0,"新订单"),(1,"应答"),(2, "派单"),(3,"接单"),(4,"完成"),(5,"评价")
    """

    def hasTimeOut(pid):
        """检测门店有效期"""
        try:
            r = AllinpayPlacedeatList.objects.get(pid=pid)
        except BaseException as err:
            logger.warn(f"[呼叫服务][失败]: 门店 {pid} 门店有效期不存在")
            return False
        else:
            if r.deatdate > date.today():
                return True
            else:
                logger.warn(f"[呼叫服务][失败]: 门店 {pid} 门店有效期已过期")
                return False

    def Select_onPost(pid=1000001):
        """查询在岗员工真实ID列表"""
        r = AllinpayPlacestaffPost.objects.filter(status=1).values_list("id", flat=True)
        s = AllinpayPlacestaffList.objects.filter(
            id__in=list(r), status=1, pid=pid
        ).values_list("sid", flat=True)
        return list(s)

    def Select_Callme_Conf(pid=1000001, cid=1):
        """查询拥有呼叫职业技能员工真实ID列表"""
        r = AllinpayCallmePost.objects.filter(pid=pid, cid=cid, status=1).values_list(
            "sid", flat=True
        )
        return list(r)

    def Select_onStaff(sid):
        """查询员工"""
        try:
            r = AllinpayStaffList.objects.get(id=sid)
        except BaseException as err:
            return None
        else:
            return r

    def Select_onPlace(pid):
        """查询场所"""
        try:
            r = AllinpayPlaceList.objects.get(id=pid)
        except BaseException as err:
            return None
        else:
            return r

    logger.info(f'新的呼叫订单: {kwargs.get("id")}')

    try:
        instance = AllinpayCallmeList.objects.get(id=kwargs.get("id"))
    except BaseException as err:
        logger.warning(f"查询呼叫订单失败: {err}")
        return {"rescode": 400, "resmsg": f"查询呼叫订单失败: {err}"}
    else:
        if not hasTimeOut(instance.pid):
            return {"rescode": 400, "resmsg": f"查询场所有效期失败"}
    try:
        conf = AllinpayCallmeConf.objects.get(id=instance.rtype, status=1)
    except BaseException as err:
        logger.warning(f"查询呼叫配置失败: {err}")
        return {"rescode": 400, "resmsg": "Conf type is err"}

    if instance.target:
        # 修改参数
        try:
            instance.answer = 0
            instance.antime = timezone.now()
            instance.status = 2
            instance.save()
        except BaseException as err:
            return {"rescode": 400, "resmsg": f"修改呼叫订单状态失败 [{err}]"}

        # 发送派单通知
        # if not settings.DEBUG:
        staff = Select_onStaff(instance.target)
        if not staff.openid:
            logger.warning(f"[{uid}] 发送模板消息失败,当前员工未绑定微信")
            return {"rescode": 400, "resmsg": "staff is not wechat"}

        place = Select_onPlace(instance.pid)
        if not place:
            logger.warning(f"[{uid}] 发送模板消息失败,查询场所失败")
            return {"rescode": 400, "resmsg": "Place is not find"}

        # timeout = str(timezone.now() + timedelta(seconds=conf.timeout)).split(".")[0]
        timeout = str(timezone.now()).split(".")[0]
        # 发送微信消息
        WeAppsUniformSend.apply_async(
            (
                staff.openid,
                f"{conf.appurl}?pid={instance.pid}",
                "收到客户新订单通知",
                [
                    instance.id,
                    conf.name,
                    place.name + "-" + kwargs.get("source") + "号机",
                    timeout,
                ],
            )
        )
        # 发送消息队列 Pulsar
        res = doCallmeEvent.apply_async((instance.id,))
        # 记录日志
        logger.info(f"[callme] 指定目标的呼叫，直接派单成功 {instance.id}")
        return {
            "rescode": 200,
            "resmsg": f"[{instance.id}] 派单完成 [{instance.reqsn}] [{staff.basename}]",
        }

    if conf.dispatch == 0:
        """前台应答,手动派单,发送队列消息"""
        return {"rescode": 200, "resmsg": "呼叫成功,请等待前台派单"}
    elif conf.dispatch == 1:
        """随机派单模式, 发送微信消息"""
        allStaff = Select_onPost(pid=kwargs.get("pid"))
        doConf = Select_Callme_Conf(pid=kwargs.get("pid"), cid=kwargs.get("rtype"))
        # 查询交集
        nowStaff = list(set(allStaff).intersection(set(doConf)))
        if not nowStaff:
            logger.warning(f'[{kwargs.get("pid")}] 当前员工坐席忙')
            return {"rescode": 400, "resmsg": "not find staff"}
        uid = random.choice(nowStaff)

        # 修改参数
        try:
            instance.target = uid
            instance.answer = 0
            instance.antime = timezone.now()
            instance.status = 2
            instance.save()
        except BaseException as err:
            return {"rescode": 400, "resmsg": f"修改呼叫订单状态失败 [{err}]"}

        # 发送派单通知
        # if not settings.DEBUG:
        staff = Select_onStaff(uid)
        if not staff.openid:
            logger.warning(f"[{uid}] 发送模板消息失败,当前员工未绑定微信")
            return {"rescode": 400, "resmsg": "staff is not wechat"}

        place = Select_onPlace(instance.pid)
        if not place:
            logger.warning(f"[{uid}] 发送模板消息失败,查询场所失败")
            return {"rescode": 400, "resmsg": "Place is not find"}

        # timeout = str(timezone.now() + timedelta(seconds=conf.timeout)).split(".")[0]
        timeout = str(timezone.now()).split(".")[0]
        # 发送微信消息
        WeAppsUniformSend.apply_async(
            (
                staff.openid,
                f"{conf.appurl}?pid={instance.pid}",
                "收到客户新订单通知",
                [
                    instance.id,
                    conf.name,
                    place.name + "-" + kwargs.get("source") + "号机",
                    timeout,
                ],
            )
        )
        # 发送消息队列 Pulsar
        res = doCallmeEvent.apply_async((instance.id,))
        # 记录日志
        logger.info(f"[callme] 随机派单成功 {instance.id} {uid}/{nowStaff}")
        return {
            "rescode": 200,
            "resmsg": f"[{instance.id}] 派单完成 [{instance.reqsn}] [{staff.basename}]",
        }
    elif conf.dispatch == 2:
        """轮流派单模式"""
        allStaff = Select_onPost(pid=kwargs.get("pid"))
        doConf = Select_Callme_Conf(pid=kwargs.get("pid"), cid=kwargs.get("rtype"))
        # 查询交集
        nowStaff = list(set(allStaff).intersection(set(doConf)))
        if not nowStaff:
            logger.warning(f'[{kwargs.get("pid")}] 当前员工坐席忙')
            return {"rescode": 400, "resmsg": "当前缺少合适的值班人员"}
        c = REDIS.redis_hash_key("sysconf", "Count")
        REDIS.redis_set_key("sysconf", "Count", int(c) + 1)
        uid = nowStaff[int(c) % len(nowStaff)]

        # 修改参数
        try:
            instance.target = uid
            instance.answer = 0
            instance.antime = timezone.now()
            instance.status = 2
            instance.save()
        except BaseException as err:
            return {"rescode": 400, "resmsg": f"修改呼叫订单状态失败 [{err}]"}

        # 发送派单通知
        # if not settings.DEBUG:
        staff = Select_onStaff(uid)
        if not staff.openid:
            logger.warning(f"[{uid}] 发送模板消息失败,当前员工未绑定微信")
            return {"rescode": 400, "resmsg": "staff is not wechat"}

        place = Select_onPlace(instance.pid)
        if not place:
            logger.warning(f"[{uid}] 发送模板消息失败,查询场所失败")
            return {"rescode": 400, "resmsg": "Place is not find"}

        # timeout = str(timezone.now() + timedelta(seconds=conf.timeout)).split(".")[0]
        timeout = str(timezone.now()).split(".")[0]
        # 发送微信消息
        WeAppsUniformSend.apply_async(
            (
                staff.openid,
                f"{conf.appurl}?pid={instance.pid}",
                "收到客户新订单通知",
                [
                    instance.id,
                    conf.name,
                    place.name + "-" + kwargs.get("source") + "号机",
                    timeout,
                ],
            )
        )
        # 发送消息队列 Pulsar
        res = doCallmeEvent.apply_async((instance.id,))
        # 记录日志
        logger.info(f"[callme] 轮流派单成功 {instance.id} {c}/{nowStaff}={uid}")
        return {
            "rescode": 200,
            "resmsg": f"[{instance.id}] 派单完成 [{instance.reqsn}] [{staff.basename}]",
        }
    elif conf.dispatch == 3:
        """抢单模式"""
        allStaff = Select_onPost(pid=kwargs.get("pid"))
        doConf = Select_Callme_Conf(pid=kwargs.get("pid"), cid=kwargs.get("rtype"))
        # 查询交集
        nowStaff = list(set(allStaff).intersection(set(doConf)))
        if not nowStaff:
            logger.warning(f'[{kwargs.get("pid")}] 当前员工坐席忙')
            return {"rescode": 400, "resmsg": "当前缺少合适的值班人员"}

        # 修改参数
        try:
            instance.target = None
            instance.answer = 0
            instance.antime = timezone.now()
            instance.status = 2
            instance.save()
        except BaseException as err:
            return {"rescode": 400, "resmsg": f"修改呼叫订单状态失败 [{err}]"}

        for uid in nowStaff:
            # if settings.DEBUG:
            #     break
            # 发送派单通知
            staff = Select_onStaff(uid)
            if not staff.openid:
                logger.warning(f"[{uid}] 发送模板消息失败,当前员工未绑定微信")
                return {"rescode": 400, "resmsg": "staff is not wechat"}

            place = Select_onPlace(instance.pid)
            if not place:
                logger.warning(f"[{uid}] 发送模板消息失败,查询场所失败")
                return {"rescode": 400, "resmsg": "Place is not find"}

            # timeout = str(timezone.now() + timedelta(seconds=conf.timeout)).split(".")[0]
            timeout = str(timezone.now()).split(".")[0]
            # 发送微信消息
            WeAppsUniformSend.apply_async(
                (
                    staff.openid,
                    f"{conf.appurl}?pid={instance.pid}",
                    "收到客户新订单通知",
                    [
                        instance.id,
                        conf.name,
                        place.name + "-" + kwargs.get("source") + "号机",
                        timeout,
                    ],
                )
            )
        # 发送消息队列 Pulsar
        res = doCallmeEvent.apply_async((instance.id,))
        # 记录日志
        logger.info(f"[callme] 抢单模式 {instance.id} {nowStaff}")
        return {
            "rescode": 200,
            "resmsg": f"[{instance.id}] 派单完成 [{instance.reqsn}] [ALL]",
        }
    elif conf.dispatch == 4:
        """固定指派"""
        allStaff = Select_onPost(pid=kwargs.get("pid"))
        doConf = Select_Callme_Conf(pid=kwargs.get("pid"), cid=kwargs.get("rtype"))
        # 查询交集
        nowStaff = list(set(allStaff).intersection(set(doConf)))
        if not nowStaff:
            logger.warning(f'[{kwargs.get("pid")}] 当前员工坐席忙')
            return {"rescode": 400, "resmsg": "当前缺少合适的值班人员"}
        if not kwargs.get("target") or not kwargs.get("target") in nowStaff:
            logger.warning(f'[{kwargs.get("pid")}] 当前员工未评级或未指定员工')
            return {"rescode": 400, "resmsg": "当前员工未评级或未指定员工"}

        # 修改参数
        try:
            instance.answer = 0
            instance.antime = timezone.now()
            instance.status = 2
            instance.save()
        except BaseException as err:
            return {"rescode": 400, "resmsg": f"修改呼叫订单状态失败 [{err}]"}

        # 发送派单通知
        staff = Select_onStaff(instance.target)
        if not staff.openid:
            logger.warning(f"[{uid}] 发送模板消息失败,当前员工未绑定微信")
            return {"rescode": 400, "resmsg": "staff is not wechat"}

        place = Select_onPlace(instance.pid)
        if not place:
            logger.warning(f"[{uid}] 发送模板消息失败,查询场所失败")
            return {"rescode": 400, "resmsg": "Place is not find"}

        # timeout = str(timezone.now() + timedelta(seconds=conf.timeout)).split(".")[0]
        timeout = str(timezone.now()).split(".")[0]
        # 发送微信消息
        WeAppsUniformSend.apply_async(
            (
                staff.openid,
                f"{conf.appurl}?pid={instance.pid}",
                "收到客户新订单通知",
                [
                    instance.id,
                    conf.name,
                    place.name + "-" + kwargs.get("source") + "号机",
                    timeout,
                ],
            )
        )
        # 发送消息队列 Pulsar
        res = doCallmeEvent.apply_async((instance.id,))
        # 记录日志
        logger.info(f"[callme] 固定指派成功 {instance.id} {instance.target}")
        return {
            "rescode": 200,
            "resmsg": f"[{instance.id}] 派单完成 [{instance.reqsn}] [{staff.basename}]",
        }
    else:
        return {"rescode": 400, "resmsg": "呼叫失败,错误的请求"}
